package com.hbx.service.impl;

import com.hbx.constant.DateFormatContent;
import com.hbx.logs.SearchResp;
import com.hbx.logs.es.EsTemplate;
import com.hbx.mapper.BlogMapper;
import com.hbx.mapper.PkMapper;
import com.hbx.mapper.ResourceMapper;
import com.hbx.mapper.UserMapper;
import com.hbx.model.Blog;
import com.hbx.model.Pk;
import com.hbx.model.Resource;
import com.hbx.model.User;
import com.hbx.service.StatisticsService;
import com.hbx.utils.DateUtil;
import com.hbx.utils.Result;
import com.hbx.vo.echarts.DateWeekHandlerVo;
import com.hbx.vo.echarts.OperaLogCountVo;
import com.hbx.vo.echarts.PushCountVo;
import com.hbx.vo.echarts.WeekRegisterVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/*
 * @Author:hbx
 * 
 * */
@Service
@Slf4j
public class StatisticsServiceImpl implements StatisticsService {

    @Autowired
    private ResourceMapper resourceMapper;

    @Autowired
    private PkMapper pkMapper;

    @Autowired
    private BlogMapper blogMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private EsTemplate esTemplate;
    /**
     * 统计发布量
     * @param r
     */
    @Override
    public void getPushCount(Result r) {
        PushCountVo vo = new PushCountVo();
        List<PushCountVo.BinVo> todayList = new ArrayList<>();
        List<PushCountVo.BinVo> allList = new ArrayList<>();
        List<Resource> resources = resourceMapper.selectList(null);
        List<Blog> blogs = blogMapper.selectList(null);
        List<Pk> pks = pkMapper.selectList(null);
        if (resources != null){
            long todaycount = resources.stream().filter(res -> {
                return res.getResIsDeleted() == 0 &&
                        DateUtil.dateToString(res.getResPushTime(), DateFormatContent.YYYY_MM_DD).equals(DateUtil.dateToString(new Date(), DateFormatContent.YYYY_MM_DD));
            }).count();
            long count = resources.stream().filter(res -> res.getResIsDeleted() == 0).count();
            todayList.add(new PushCountVo.BinVo("资源", todaycount));
            allList.add(new PushCountVo.BinVo("资源", count));
        } else {
            todayList.add(new PushCountVo.BinVo("资源", 0L));
            allList.add(new PushCountVo.BinVo("资源", 0L));
        }

        if (blogs != null){
            long todaycount = blogs.stream().filter(blog -> {
                return blog.getBlogIsDeleted() == 0 &&
                        DateUtil.dateToString(blog.getBlogPushTime(), DateFormatContent.YYYY_MM_DD).equals(DateUtil.dateToString(new Date(), DateFormatContent.YYYY_MM_DD));
            }).count();
            long count = blogs.stream().filter(res -> res.getBlogIsDeleted() == 0).count();
            todayList.add(new PushCountVo.BinVo("博客", todaycount));
            allList.add(new PushCountVo.BinVo("博客", count));
        } else {
            todayList.add(new PushCountVo.BinVo("博客", 0L));
            allList.add(new PushCountVo.BinVo("博客", 0L));
        }

        if (pks != null){
            long todaycount = pks.stream().filter(pk -> {
                return pk.getPkDelete() == 0 &&
                        DateUtil.dateToString(pk.getPkPublishTime(), DateFormatContent.YYYY_MM_DD).equals(DateUtil.dateToString(new Date(), DateFormatContent.YYYY_MM_DD));
            }).count();
            long count = pks.stream().filter(pk -> pk.getPkDelete() == 0).count();
            todayList.add(new PushCountVo.BinVo("PK", todaycount));
            allList.add(new PushCountVo.BinVo("PK", count));
        } else {
            todayList.add(new PushCountVo.BinVo("PK", 0L));
            allList.add(new PushCountVo.BinVo("PK", 0L));
        }
        vo.setTodayData(todayList);
        vo.setAllData(allList);
        r.setCode(200).setData(vo);
    }

    /**
     * 统计7日注册数
     * @param r
     */
    @Override
    public void getWeeksRegisterCount(Result r) {
        WeekRegisterVo vo = new WeekRegisterVo();
        List<String> dayWeekList = new ArrayList<>();
        List<Integer> countList = new ArrayList<>();
        LocalDate today = LocalDate.now();
        LocalDate beforeWeek = today.minusWeeks(1);
        List<DateWeekHandlerVo> localDate = getLocalDate(beforeWeek);
        List<User> list = userMapper.getWeeksRegisterList(beforeWeek.toString(), today.toString());
        if (CollectionUtils.isEmpty(list)){
            localDate.stream().forEach(d -> {
                dayWeekList.add(d.getDateValue());
                countList.add(0);
            });
        } else {
            Map<Date, List<User>> listMap = list.stream().collect(Collectors.groupingBy(User::getRegisterTime));
            localDate.stream().forEach(d -> {
                dayWeekList.add(d.getDateValue());
                boolean flag = false;
                for (Map.Entry<Date,List<User>> entry : listMap.entrySet()){
                    if (DateUtil.dateToString(entry.getKey(), DateFormatContent.YYYY_MM_DD).equals(d.getDate())){
                        countList.add(entry.getValue().size());
                        flag = true;
                    }
                }
                if (!flag){
                    countList.add(0);
                }
            });
        }
        vo.setWeeks(dayWeekList);
        vo.setValue(countList);
        r.setCode(200).setData(vo);
    }

    /**
     * 今日操作数
     * @param r
     */
    @Override
    public void getOperaLogsCount(Result r) {
        OperaLogCountVo vo = new OperaLogCountVo();
        List<String> dates = new ArrayList<>();
        List<Integer> values = new ArrayList<>();
        LocalDateTime now = LocalDateTime.now();
        int hour = now.getHour();
        if (hour == 0){
            dates.add("1:00");
            SearchResp result = esTemplate.getLogsByDate(DateUtil.dateToString(DateUtil.getHourDate(0), DateFormatContent.YYYY_MM_DD_HH_MM_SS),
                    DateUtil.dateToString(DateUtil.getHourDate(1), DateFormatContent.YYYY_MM_DD_HH_MM_SS));
            if (result != null && result.getLogsList() != null){
                values.add(result.getLogsList().size());
            } else {
                values.add(0);
            }
        } else {
            for (int i = 1; i <= hour; i++) {
                SearchResp result = esTemplate.getLogsByDate(DateUtil.dateToString(DateUtil.getHourDate(i - 1), DateFormatContent.YYYY_MM_DD_HH_MM_SS),
                        DateUtil.dateToString(DateUtil.getHourDate(i), DateFormatContent.YYYY_MM_DD_HH_MM_SS));
                dates.add(i + ":00");
                if (result != null && result.getLogsList() != null){
                    values.add(result.getLogsList().size());
                } else {
                    values.add(0);
                }
            }
        }
        vo.setTimes(dates);
        vo.setValues(values);
        r.setCode(200).setData(vo);
    }

    private List<DateWeekHandlerVo> getLocalDate(LocalDate beforeWeek){
        SimpleDateFormat format = new SimpleDateFormat(DateFormatContent.YYYY_MM_DD);
        List<DateWeekHandlerVo> mapHandler = new ArrayList<>();
        try {
            for (int i = 0; i < 7; i++) {
                Date parse = format.parse(beforeWeek.toString());
                String value = DateUtil.getWeekOfDate(parse);
                DateWeekHandlerVo vo = new DateWeekHandlerVo();
                vo.setDate(beforeWeek.toString());
                vo.setDateValue(value);
                mapHandler.add(vo);
                beforeWeek = beforeWeek.plusDays(1);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return mapHandler;
    }
}
